# !/usr/bin/python3
# -*- coding:utf-8 -*-
"""
@file: switch_ip.py
@desc: 定时每5分钟切换代理IP（使用SwitchyOmega插件控制代理）
@time: 2025/4/23 22:05
@desc:

"""
import requests

R"""
1. chrome s商店下载Proxy SwitchyOmega 3 (ZeroOmega)插件 并且到 C:\Users\v_jiaohaicheng\AppData\Local\Google\Chrome\User Data\Default\Extensions\pfnededegaaopdmhkdmcofjmoldfiped\3.3.23_0 中复制全部内容
替换 https://github.com/zero-peak/ZeroOmega/releases 里的.xpi 文件解压后的文件 以保证插件能够正常被加载
2. 插件配置页 chrome-extension://pfnededegaaopdmhkdmcofjmoldfiped/options.html#!/profile/proxy
3.

"""
import time
import atexit
from DrissionPage import WebPage, ChromiumOptions, SessionOptions
from urllib.parse import urlparse
from loguru import logger

# ========== 配置区域 ==========
DEFAULT_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0"
EXTENSIONS_ZEROOMEGA = r"C:\Users\15118\AppData\Local\Google\Chrome\User Data\Default\Extensions\pfnededegaaopdmhkdmcofjmoldfiped\3.4.1_0"
CHROME_PATH = r"C:\Program Files\Google\Chrome\Application\chrome.exe"
PROXY_API = 'http://123.56.42.142:5000/proxy/getitem/'

# ========== 获取代理 ==========
def get_random_proxy():
    try:
        response = requests.get(PROXY_API, timeout=10)
        proxy_data = response.json().get('proxy', {})
        proxy_url = proxy_data.get('http') or proxy_data.get('https')
        if not proxy_url:
            return None, None, None, None

        parsed = urlparse(proxy_url)
        ip = parsed.hostname            # '123.134.185.67'
        port = str(parsed.port)         # '58116'
        username = parsed.username      # 'dwe20241014'
        password = parsed.password      # 'Dwe0101014'

        return ip, port, username, password

    except Exception as e:
        logger.error(f"[×] 获取代理失败: {e}")
        return None, None, None, None

# ========== 浏览器控制类 ==========
class DrissionPageDemo(object):
    """

    """

    def __init__(self):
        """

        """
        atexit.register(self.exit_handler)
        self.page = None

    def exit_handler(self):
        """

        :return:
        """
        if self.page:
            self.page.quit(del_data=True)

    def get_page(self, ua=None, cookies=None, incognito=True, time_out=60):
        """

        :param ua:
        :param cookies:
        :param incognito:
        :param time_out:
        :param headless:
        :return:
        """
        if not self.page:
            co = ChromiumOptions()
            so = SessionOptions()
            if cookies:
                so.set_cookies(cookies)
            if not ua:
                ua = DEFAULT_UA
            co.set_user_agent(user_agent=ua)
            co.set_argument('--no-sandbox')
            co.set_argument("--disable-gpu")
            co.ignore_certificate_errors(incognito)
            # co.add_extension(EXTENSIONS_ZEROOMEGA)

            co.set_argument('--load-extension=' + EXTENSIONS_ZEROOMEGA)  # 手动指定插件目录
            co.set_argument('--disable-extensions-except=' + EXTENSIONS_ZEROOMEGA)  # 只启用这个插件
            co.set_argument('--disable-blink-features=AutomationControlled')  # 隐藏自动化痕迹

            # ✅ 禁止加载图片
            co.set_pref('profile.managed_default_content_settings.images', 2)

            # co.set_browser_path(CHROME_PATH)
            co.mute(True)
            co.auto_port()
            co.set_timeouts(page_load=time_out)
            self.page = WebPage(chromium_options=co, session_or_options=so)
        return self.page

    def get_js(self, ip, port, username="", password=""):
        """
        生成设置 IP、端口、点击“代理登录”、填写账号密码并应用 的 JavaScript
        """
        js_code = f"""
            var tdElements = document.querySelectorAll('td[ng-if="proxyEditors[scheme].scheme"].ng-scope');

            if (tdElements.length > 1) {{
                var firstTdElement = tdElements[0];
                var firstInputElement = firstTdElement.querySelector('input[type="text"]');
                if (firstInputElement) {{
                    firstInputElement.value = '{ip}';
                    firstInputElement.dispatchEvent(new Event('input', {{ bubbles: true, cancelable: true }}));
                    console.log('设置 IP:', firstInputElement.value);
                }}

                var secondTdElement = tdElements[1];
                var secondInputElement = secondTdElement.querySelector('input[type="number"]');
                if (secondInputElement) {{
                    secondInputElement.value = '{port}';
                    secondInputElement.dispatchEvent(new Event('input', {{ bubbles: true, cancelable: true }}));
                    console.log('设置端口:', secondInputElement.value);
                }}
            }}

            // 点击“代理登录”按钮
            var authBtn = document.querySelector('button[title="代理登录"]');
            if (authBtn) {{
                authBtn.click();
                console.log('点击了“代理登录”按钮');
            }} else {{
                console.log('未找到“代理登录”按钮');
                return false;
            }}

            // 延时设置账号密码（给界面切换时间）
            setTimeout(function() {{
                var userInput = document.querySelector('input[placeholder="用户名"]');
                if (userInput) {{
                    userInput.value = '{username}';
                    userInput.dispatchEvent(new Event('input', {{ bubbles: true, cancelable: true }}));
                    console.log('设置用户名:', userInput.value);
                }}

                var passInput = document.querySelector('input[placeholder="密码"]');
                if (passInput) {{
                    passInput.value = '{password}';
                    passInput.dispatchEvent(new Event('input', {{ bubbles: true, cancelable: true }}));
                    console.log('设置密码:', passInput.value);
                }}
                
                // 点击“保存更改”按钮
                var saveBtn = document.querySelector('button[type="submit"]');
                if (saveBtn) {{
                    saveBtn.click();
                    console.log('点击保存按钮');
                }} else {{
                    console.log('未找到保存按钮');
                }}

                var applyButton = document.querySelector('a[ng-click="applyOptions()"]');
                if (applyButton) {{
                    applyButton.click();
                    console.log('点击应用按钮');
                }} else {{
                    console.log('未找到应用按钮');
                }}
            }}, 500);  // 延迟 500ms 再设置账号密码

            return true;
        """
        return js_code


    def load_extensions_default_config(self):
        """
        启动浏览器后先加载插件默认配置
        :return:
        """
        url_config = "chrome-extension://pfnededegaaopdmhkdmcofjmoldfiped/options.html#!/io"
        # url_config = "chrome-extension://padekgcemlokbadohgkifijomclgjgif/options.html#!/io"
        config_url = "https://bj.bcebos.com/petite-mark/public_read/vipshop/ZeroOmegaOptions.bak"

        js = """

                    var inputElement = document.querySelector('input[ng-model="restoreOnlineUrl"]');
                    if (inputElement){
                        inputElement.value = '""" + config_url + """'; 
                        var event = new Event('input');
                        inputElement.dispatchEvent(event);
                    }else{
                        return false;
                    }


                    var buttonElement = document.querySelector('button[ng-click="restoreOnline()"]');
                    if (buttonElement){
                        buttonElement.click();
                        return true;
                    }else{
                        return false;
                    }


                """
        self.page.get(url_config, retry=3, interval=3)
        self.page.wait.eles_loaded("#restoreOnline")
        status = self.page.run_js(js)
        self.page.wait.eles_loaded("#ladda-progress")
        self.page.wait(1)
        return status

    def switch_ip(self, ip, port,username,password):
        """
        切换ip
        :return:
        """
        url = "chrome-extension://pfnededegaaopdmhkdmcofjmoldfiped/options.html#!/profile/proxy"
        self.page.get(url, retry=3, interval=3)
        self.page.wait.eles_loaded("#restoreOnline")
        # status = self.page.run_js(self.get_js(ip, port))
        status = self.page.run_js(self.get_js(ip, port, username, password))
        self.page.wait(1)
        return status


    def check_ip(self):
        """

        :return:
        """
        js = """return document.getElementById("tab0_ip").innerText;"""
        res = self.page.run_js(js)
        while res == "加载中..." or res == "":
            res = self.page.run_js(js)
            time.sleep(1)
        return res

    def get_page_instance(self):
        """返回当前浏览器实例，用于爬虫使用"""
        return self.page

    def process(self, url, interval=300):
        """

        :param url:
        :return:
        """
        self.get_page()
        # 首次启动浏览器加载插件默认配置 保证插件以proxy模式运行
        if not self.load_extensions_default_config():
            print("加载插件默认配置失败")
            return

        last_ip = None

        while True:
            new_ip, port, username, password = get_random_proxy()
            if not new_ip:
                logger.error("[×] 未获取到代理，等待重试")
                time.sleep(interval)
                continue

            logger.info(f"[*] 尝试切换代理为 {new_ip}:{port}")
            if self.switch_ip(new_ip, port, username, password):
                try:
                    self.page.get(url)
                    current_ip = self.check_ip()
                    if current_ip != last_ip:
                        logger.info(f"[✓] 成功切换为新IP: {current_ip}")
                        last_ip = current_ip
                    else:
                        logger.error("[×] IP未变，可能切换失败或IP无效")
                except Exception as e:
                    logger.error(f"[×] 页面访问失败: {e}")
            else:
                logger.error("[×] 执行代理切换失败")

            logger.info(f"[*] 等待 {interval} 秒后重试...\n")
            time.sleep(interval)



if __name__ == '__main__':
    page = DrissionPageDemo()
    url = "https://ip.cn/"
    page.process(url)


